<?php
declare(strict_types=1);

namespace app\common\service;

use app\common\model\Admin as AdminModel;
use app\common\model\AdminToken as AdminTokenModel;
use think\facade\Request;
use think\facade\Db;

class AdminService
{
    protected AdminModel $adminModel;
    protected AdminTokenModel $tokenModel;
    
    public function __construct()
    {
        $this->adminModel = new AdminModel();
        $this->tokenModel = new AdminTokenModel();
    }
    
    /**
     * 管理员登录
     * @param string $username
     * @param string $password
     * @param int $expireHours token有效期(小时)
     * @return array
     * @throws \Exception
     */
    public function login(string $username, string $password, int $expireHours = 24): array
    {
        // 获取管理员信息
        $admin = $this->adminModel->getAdminByUsername($username);
        if (!$admin) {
            throw new \Exception('用户名或密码错误');
        }
        
        // 验证密码
        // 使用密码盐加密验证
        $encryptedPassword = md5($password . $admin['salt']);
        if ($encryptedPassword !== $admin['password']) {
            throw new \Exception('用户名或密码错误');
        }
        
        // 生成token
        $token = $this->generateToken();
        
        // 保存token
        $this->tokenModel->saveToken($admin['admin_id'], $token, $expireHours);
        
        // 更新登录信息
        $this->adminModel->updateLoginInfo($admin['admin_id'], Request::ip());
        
        // 清理该用户的过期token
        $this->tokenModel->where('admin_id', $admin['admin_id'])
            ->where('expire_time', '<=', date('Y-m-d H:i:s'))
            ->delete();
        
        return [
            'token' => $token,
        ];
    }
    
    /**
     * 生成token
     * @return string
     */
    protected function generateToken(): string
    {
        $uuid = sprintf(
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff)
        );
        return $uuid;
    }
    
    /**
     * 验证token
     * @param string $token
     * @return array
     * @throws \Exception
     */
    public function verifyToken(string $token): array
    {
        $tokenInfo = $this->tokenModel->getTokenInfo($token);
        if (!$tokenInfo) {
            throw new \Exception('登录已过期，请重新登录');
        }
        
        // 获取管理员信息
        $admin = $this->adminModel->find($tokenInfo['admin_id']);
        if (!$admin || $admin['status'] != 1) {
            throw new \Exception('账号已被禁用');
        }
        
        return [
            'admin_id' => $admin['admin_id'],
            'username' => $admin['username'],
            'expire_time' => $tokenInfo['expire_time']
        ];
    }
    
    /**
     * 获取管理员信息
     * @param int $adminId
     * @return array
     * @throws \Exception
     */
    public function getAdminInfo(int $adminId): array
    {
        $admin = $this->adminModel->find($adminId);
        if (!$admin || $admin['status'] != 1) {
            throw new \Exception('账号不存在或已被禁用');
        }
        
        // 获取角色和权限
        $roles = $this->adminModel->getAdminRoles($adminId);
        $permissions = $this->adminModel->getAdminPermissions($adminId);
        
        // 如果是超级管理员，给予所有权限
        if (in_array('super_admin', $roles)) {
            $permissions = Db::name('menu')
                ->where('status', 1)
                ->where('perms', '<>', '')
                ->column('perms');
        }
        
        return [
            'username' => $admin['nickname'],
            'roles' => $roles,
            'permissions' => $permissions,
            'avatar' => $admin['avatar'] ?: 'https://i.gtimg.cn/club/item/face/img/2/16022_100.gif'
        ];
    }
    
    /**
     * 退出登录
     * @param string $token
     * @return bool
     */
    public function logout(string $token): bool
    {
        // 删除token
        return (bool)$this->tokenModel->where('token', $token)->delete();
    }
} 